home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / lang / SmallEiffel.lha / SmallEiffel / lib_se / e_feature.e < prev    next >
Text File  |  1998-12-22  |  12KB  |  499 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. deferred class E_FEATURE
  17.    --
  18.    -- For all possible Features : procedure, function, attribute, 
  19.    -- constants, once procedure, once function, ...
  20.    --   
  21.  
  22. inherit GLOBALS;
  23.    
  24. feature  
  25.    
  26.    base_class: BASE_CLASS;
  27.      -- The class where the feature is really written.
  28.    
  29.    names: FEATURE_NAME_LIST; 
  30.      -- All the names of the feature.
  31.    
  32.    arguments: FORMAL_ARG_LIST is
  33.      -- Arguments if any.
  34.       deferred
  35.       end;
  36.    
  37.    result_type: TYPE is
  38.      -- Result type if any.
  39.       deferred
  40.       end;
  41.    
  42.    header_comment: COMMENT;
  43.      -- Header comment for a routine or following comment for
  44.      -- an attribute.
  45.    
  46.    require_assertion: E_REQUIRE is
  47.      -- Not Void if any.
  48.       deferred
  49.       end;
  50.    
  51.    ensure_assertion: E_ENSURE is
  52.      -- Not Void if any.
  53.       deferred
  54.       end;
  55.    
  56.    local_vars: LOCAL_VAR_LIST;
  57.      -- Local var list if any.
  58.    
  59.    clients: CLIENT_LIST;
  60.      -- Authorized clients list of the corresponding feature
  61.      -- clause in the base definition class.
  62.    
  63.    is_deferred: BOOLEAN is
  64.      -- Is it a deferred feature ?
  65.       deferred
  66.       end;
  67.    
  68.    frozen mapping_c_name_in(str: STRING) is
  69.       do
  70.      base_class.mapping_c_in(str);
  71.      str.append(first_name.to_key);
  72.       end;
  73.  
  74.    frozen mapping_c_name is
  75.       local
  76.      s: STRING;
  77.       do
  78.      s := "    ";
  79.      s.clear;
  80.      mapping_c_name_in(s);
  81.      cpp.put_string(s);
  82.       end;
  83.    
  84.    base_class_name: CLASS_NAME is
  85.      -- Name of the class where the feature is really written.
  86.       do
  87.      Result := base_class.name;
  88.       end;
  89.    
  90.    frozen first_name: FEATURE_NAME is
  91.      -- Return the principal (first) name of the feature.
  92.       do
  93.      Result := names.item(1);
  94.       ensure
  95.      Result /= void
  96.       end; 
  97.  
  98.    start_position: POSITION is
  99.       do
  100.      Result := first_name.start_position;
  101.       end;
  102.    
  103.    to_run_feature(t: TYPE; fn: FEATURE_NAME): RUN_FEATURE is
  104.      -- If possible, gives the checked runnable feature for `t'. 
  105.      -- Note: corresponding run_class dictionary is updated
  106.      --       with this new feature.
  107.       require
  108.      t.is_run_type;
  109.      fn /= Void;
  110.       deferred
  111.       ensure
  112.      Result /= Void implies t.run_class.at(fn) = Result;
  113.      Result = Void implies nb_errors > 0
  114.       end;
  115.    
  116.    can_hide(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
  117.      -- True when headings of Current can be hide with
  118.      -- heading of `other' in `rc'.
  119.       require
  120.      Current /= other;
  121.       do
  122.      if result_type /= other.result_type then
  123.         if result_type = Void or else other.result_type = Void then
  124.            eh.add_position(other.start_position);
  125.            error(start_position,"One has Result but not the other.");
  126.         end;
  127.      end;
  128.      if arguments /= other.arguments then
  129.         if arguments = Void or else other.arguments = Void then
  130.            eh.add_position(other.start_position);
  131.            error(start_position,"One has argument(s) but not the other.");
  132.         elseif arguments.count /= other.arguments.count then 
  133.            eh.add_position(other.start_position);
  134.            error(start_position,"Incompatible number of arguments.");
  135.         end;
  136.      end;
  137.      if nb_errors = 0 then
  138.         if result_type /= Void then
  139.            if not result_type.is_a_in(other.result_type,rc) then
  140.           eh.append(em1);
  141.           eh.append(rc.current_type.run_time_mark);
  142.           eh.error(fz_dot);
  143.            end;
  144.         end;
  145.      end;
  146.      if nb_errors = 0 then
  147.         if arguments /= Void then
  148.            if not arguments.is_a_in(other.arguments,rc) then
  149.           eh.add_position(other.start_position);
  150.           eh.add_position(start_position)
  151.           eh.append(em1);
  152.           eh.append(rc.current_type.run_time_mark);
  153.           eh.error(fz_dot);
  154.            end;
  155.         end;
  156.      end;
  157.      Result := nb_errors = 0; 
  158.      if Result then
  159.         merge_header_comments(other);
  160.      end;
  161.       end;
  162.  
  163. feature {PARENT_LIST}
  164.  
  165.    frozen is_merge_with(other: E_FEATURE; rc: RUN_CLASS): BOOLEAN is
  166.      -- True when headings of Current can be merge with heading 
  167.      -- of `other' in `rc'.
  168.       require
  169.      Current /= other;
  170.      eh.empty
  171.       do
  172.      Result := true;
  173.      if result_type /= other.result_type then
  174.         if result_type = Void or else other.result_type = Void then
  175.            Result := false;
  176.         end;
  177.      end;
  178.      if arguments /= other.arguments then
  179.         if arguments = Void or else other.arguments = Void then
  180.            Result := false;
  181.         elseif arguments.count /= other.arguments.count then 
  182.            Result := false;
  183.         end;
  184.      end;
  185.      if Result then
  186.         if result_type /= Void then
  187.            Result := result_type.is_a_in(other.result_type,rc);
  188.         end;
  189.         if Result and then arguments /= Void then
  190.            Result := arguments.is_a_in(other.arguments,rc);
  191.         end;
  192.         if not Result then
  193.            Result := true;
  194.            eh.cancel;
  195.            if result_type /= Void then
  196.           Result := other.result_type.is_a_in(result_type,rc);
  197.            end;
  198.            if Result and then arguments /= Void then
  199.           Result := other.arguments.is_a_in(arguments,rc);
  200.            end;
  201.         end;
  202.      end;
  203.      if Result then
  204.         merge_header_comments(other);
  205.      end;
  206.       ensure
  207.      Result = eh.empty
  208.       end;
  209.    
  210. feature {PARENT}
  211.  
  212.    frozen try_to_undefine(fn: FEATURE_NAME; 
  213.               bc: BASE_CLASS): DEFERRED_ROUTINE is
  214.      -- When class `bc' has an undefine clause for `fn'.
  215.      -- Compute the corresponding undefined feature.
  216.      -- Check for (VDUS).
  217.      -- Not Void when no errors.
  218.       require
  219.      names.feature_name(fn.to_key) /= Void;
  220.      bc.name.is_subclass_of(base_class_name)
  221.       local
  222.      fn2: FEATURE_NAME;
  223.       do
  224.      -- For (VDUS) :
  225.      eh.add_position(fn.start_position);
  226.      fn2 :=  names.feature_name(fn.to_key);
  227.      if fn2 /= Void then
  228.         fn2.undefine_in(bc);
  229.      end;
  230.      eh.cancel;
  231.      --
  232.      Result := try_to_undefine_aux(fn,bc);
  233.      if Result /= Void then
  234.         Result.set_clients(clients);
  235.         merge_header_comments(Result);
  236.      else
  237.         bc.fatal_undefine(fn);
  238.      end;
  239.       ensure
  240.      Result /= Void
  241.       end;
  242.    
  243. feature {FEATURE_CLAUSE,E_FEATURE}
  244.    
  245.    set_clients(c: like clients) is
  246.       require
  247.      c /= Void;
  248.       do
  249.      clients := c;
  250.       ensure
  251.      clients = c;
  252.       end;
  253.    
  254. feature 
  255.    
  256.    set_header_comment(hc: like header_comment) is
  257.       do
  258.      header_comment := hc;
  259.       end;
  260.    
  261. feature -- Pretty printing :
  262.    
  263.    pretty_print is
  264.       require
  265.      fmt.indent_level = 1;
  266.       deferred
  267.       ensure
  268.      fmt.indent_level = 1;
  269.       end;
  270.    
  271.    frozen pretty_print_profile is
  272.       do
  273.      pretty_print_names;
  274.      fmt.set_indent_level(2);
  275.      pretty_print_arguments;
  276.      fmt.set_indent_level(3);
  277.      if result_type /= Void then
  278.         fmt.put_string(": ");
  279.         result_type.pretty_print;
  280.      end;
  281.       end;
  282.    
  283. feature {RUN_FEATURE}
  284.    
  285.    run_require(rf: RUN_FEATURE): RUN_REQUIRE is
  286.      -- Collect all (inherited) require assertions for 
  287.      -- `rf'. Unless return Void (no assertion at all).
  288.       require
  289.      rf /= Void;
  290.      rf.base_feature = Current;
  291.       local
  292.      i: INTEGER;
  293.      r: like runnable;
  294.      er: E_REQUIRE;
  295.      hc: COMMENT;
  296.      ar: ARRAY[E_REQUIRE];
  297.      ct: TYPE;
  298.       do
  299.      require_collector.clear;
  300.      ct := rf.current_type;
  301.      ct.base_class.collect_for(code_require,rf.name);
  302.      if not require_collector.empty then
  303.         from  
  304.            i := 1;
  305.         until
  306.            i > require_collector.upper
  307.         loop
  308.            er := require_collector.item(i);
  309.            hc := er.header_comment;
  310.            if not er.empty then
  311.           r := runnable(er.list,ct,rf);
  312.           if r /= Void then
  313.              !!er.make_runnable(r,ct,rf);
  314.              er.set_header_comment(hc);
  315.              if ar = Void then
  316.             ar := <<er>>;
  317.              else
  318.             ar.add_last(er);
  319.              end;
  320.           end;
  321.            end;
  322.            i := i + 1;
  323.         end;        
  324.         if ar /= Void then
  325.            !!Result.make(ar);
  326.         end;
  327.      end;
  328.       end;
  329.    
  330.    run_ensure(rf: RUN_FEATURE): E_ENSURE is
  331.       require
  332.      rf /= Void;
  333.      rf.base_feature = Current;
  334.       local
  335.      r: like runnable;
  336.      ct: TYPE;
  337.       do
  338.      assertion_collector.clear;
  339.      header_comment_memory.clear;
  340.      ct := rf.current_type;
  341.      ct.base_class.collect_for(code_ensure,rf.name);
  342.      r := runnable(assertion_collector,ct,rf);
  343.      if r /= Void then
  344.         !!Result.make_runnable(r,ct,rf);
  345.         Result.set_header_comment(header_comment_memory.item);
  346.         header_comment_memory.clear;
  347.      end;
  348.       end;
  349.    
  350. feature {NONE}
  351.    
  352.    require_collector: ARRAY[E_REQUIRE] is
  353.       once
  354.      !!Result.make(1,10);
  355.       end;
  356.    
  357.    assertion_collector: ARRAY[ASSERTION] is
  358.       once
  359.      !!Result.make(1,10);
  360.       end;
  361.    
  362.    header_comment_memory: MEMO[COMMENT] is
  363.       once
  364.      !!Result;
  365.       end;
  366.    
  367. feature {BASE_CLASS}
  368.    
  369.    collect_for(code: INTEGER) is
  370.       local
  371.      er: E_REQUIRE;
  372.       do
  373.      if code = code_require then
  374.         er := require_assertion;
  375.         if er /= Void then
  376.            if not require_collector.fast_has(er) then
  377.           require_collector.add_last(er);
  378.            end;
  379.         end;
  380.      else
  381.         check
  382.            code = code_ensure;
  383.         end;
  384.         if ensure_assertion /= Void then
  385.            header_comment_memory.set_item(ensure_assertion.header_comment);
  386.            ensure_assertion.add_into(assertion_collector);
  387.         end;
  388.      end;
  389.       end;
  390.    
  391. feature {NONE}
  392.    
  393.    frozen pretty_print_names is
  394.      -- Print only the names of the feature.
  395.       local
  396.      i: INTEGER;
  397.       do
  398.      from
  399.         i := 1;
  400.         names.item(i).declaration_pretty_print;
  401.         i := i + 1;
  402.      until
  403.         i > names.count
  404.      loop
  405.         fmt.put_string(", ");
  406.         names.item(i).declaration_pretty_print;
  407.         i := i + 1;
  408.      end;
  409.       end;
  410.    
  411.    pretty_print_arguments is
  412.       deferred
  413.       end;
  414.  
  415.    make_e_feature(n: like names) is
  416.       require
  417.      n.count >= 1;
  418.       do
  419.      names := n; 
  420.       ensure
  421.      names = n
  422.       end;
  423.    
  424. feature {FEATURE_CLAUSE}
  425.    
  426.    add_into(fd: DICTIONARY[E_FEATURE,STRING]) is
  427.      -- Also check for multiple definitions.
  428.       local
  429.      i: INTEGER;
  430.      fn: FEATURE_NAME;
  431.       do
  432.      base_class := names.item(1).start_position.base_class;
  433.      from
  434.         i := 1;
  435.      until
  436.         i > names.count
  437.      loop
  438.         fn := names.item(i);
  439.         if fd.has(fn.to_key) then
  440.            fn := fd.at(fn.to_key).first_name;
  441.            eh.add_position(fn.start_position);
  442.            eh.add_position(names.item(i).start_position);
  443.            eh.error("Double definition of feature ");
  444.            eh.append(fn.to_string);
  445.            eh.error(fz_dot);
  446.         else
  447.            fd.put(Current,fn.to_key);
  448.         end;
  449.         i := i + 1;
  450.      end;
  451.       end;
  452.  
  453. feature {C_PRETTY_PRINTER}
  454.  
  455.    stupid_switch(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS]): BOOLEAN is
  456.      -- True when it is stupid do such a switch.
  457.      -- Assume all `base_feature' of `r' is Current.
  458.       require
  459.      run_control.boost;
  460.      small_eiffel.is_ready;
  461.      up_rf.base_feature = Current;
  462.      up_rf.run_class.running = r;
  463.      r.count >= 1
  464.       deferred
  465.       end;
  466.  
  467. feature {NONE}
  468.    
  469.    try_to_undefine_aux(fn: FEATURE_NAME; 
  470.                bc: BASE_CLASS): DEFERRED_ROUTINE is
  471.       require
  472.      fn /= Void;
  473.      bc /= Void
  474.       deferred
  475.       end;
  476.  
  477.    em1: STRING is " Cannot inherit thoses features in "
  478.  
  479. feature {NONE}
  480.  
  481.    frozen merge_header_comments(other: E_FEATURE) is
  482.      -- Falling down of the `header_comment' for command short.
  483.       do
  484.      if small_eiffel.short_flag then
  485.         if header_comment = Void then
  486.            header_comment := other.header_comment;
  487.         elseif other.header_comment = Void then
  488.            other.set_header_comment(header_comment);
  489.         end;
  490.      end;
  491.       end;
  492.  
  493. invariant
  494.    
  495.    names /= Void;
  496.    
  497. end -- E_FEATURE
  498.  
  499.